Go 語言的介面(interface)是一組以方法簽名(method signatures)的組合,透過介面來定義物件的一組行為,它將物件導向的內容組織,實現得非常方便。
Interface 定義了一組 method,Interface 裡的值可以保存實現這些方法的任何值 。這裡以 Go Tutorial 上的例子來解說,這邊有稍微做了些調整,我們直接看以下的程式碼:
package main
import (
"fmt"
"math"
)
type Abser interface {
Abs() float64
}
func main() {
var a Abser
f := MyFloat(-math.Sqrt2)
v := Vertex{3, 4}
a = f // a MyFloat implements Abser
fmt.Println(a.Abs())
a = &v // a *Vertex implements Abser
fmt.Println(a.Abs())
}
type MyFloat float64
func (f MyFloat) Abs() float64 {
if f < 0 {
return float64(-f)
}
return float64(f)
}
type Vertex struct {
X, Y float64
}
func (v *Vertex) Abs() float64 {
return math.Sqrt(v.X*v.X + v.Y*v.Y)
}
我們來解釋一下上述程式碼, Abser interface 實現了 Abs method,而 Abs method 同時定義在 Vertex struct 和 MyFloat 上。
Interface 裡到底能存什麼值呢?如果我們定義了一個 interface 的變數,那麼這個變數可以實現該 interface 裡所有的變數型態。例如上述的例子, Abser interface 最終實現了 Vertex struct 和 MyFloat 兩種變數型態,而最後儲存 float64 這個變數型態。
我們再來看一個例子:
package main
import (
"fmt"
"math"
)
type I interface {
M()
}
type T struct {
S string
}
func (t *T) M() {
fmt.Println(t.S)
}
type F float64
func (f F) M() {
fmt.Println(f)
}
func main() {
var i I
i = &T{"Hello"}
describe(i)
i.M()
i = F(math.Pi)
describe(i)
i.M()
}
func describe(i I) {
fmt.Printf("(%v, %T)\n", i, i)
}
Interface I 實現了 M method,而 M method 定義在 T struct 和 F float64上,最後 M method 因出了兩個型態變數中帶的參數
空 interface 不包含任何的 method,所以所有的型別都實現了空 interface。空 interface 對於描述起不到任何的作用(因為它不包含任何的 method),但是在我們需要儲存任意型別的數值時,空 interface 及發揮到他的作用,因為它可以儲存任意變數型態,我們來看一下下面的例子:
package main
import (
"fmt"
)
var a interface{}
func main() {
// 定義 a 為空介面
var i int = 5
s := "Hello world"
// a 可以儲存任意型別的數值
a = i
fmt.Println(a) // 5
a = s
fmt.Println(a) // Hello world
}
一個 nil interface 值既不包含值也不包含具體類型。
在 nil interface 上調用方法是一個運行時錯誤,因為 interface 裡沒有任何類型定義在任何方法上。
package main
import "fmt"
type I interface {
M()
}
func main() {
var i I
describe(i)
i.M()
}
func describe(i I) {
fmt.Printf("(%v, %T)\n", i, i)
}
今天帶來 Go 語言中非常巧妙的設計 interface,它讓物件導向,內容組織實現非常的方便,本人自覺 Go 語言的 interface 簡單且非常實用,希望今天帶來的文章對你有初步認識 interface 的幫助,謝謝你今天的閱讀。
https://tour.golang.org/methods/9
https://tour.golang.org/methods/10
https://tour.golang.org/methods/11
https://tour.golang.org/methods/12
https://tour.golang.org/methods/13
https://tour.golang.org/methods/14